package com.shiro.realms;

import com.entity.SysMenu;
import com.entity.SysRole;
import com.entity.SysRoleMenu;
import com.entity.SysUser;
import com.service.SysMenuService;
import com.service.SysRoleMenuService;
import com.service.SysRoleService;
import com.service.SysUserService;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.HashSet;
import java.util.List;


/**
 * @author lanouhn
 */
public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    private SysUserService sysUserService;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private SysRoleService sysRoleService;

    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        //1.把AuthenticationToken转换为UsernamePasswordToken
        UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
        //2.从UsernamePasswordToken获取username
        String username = token.getUsername();
        //3.调用数据库的方法,从数据库中查询username对应的记录
        SysUser sysUser = sysUserService.selectSysUserByObj(new SysUser(username));
        //4.在查出这个人所对应的角色名称
        SysRole sysRole = sysRoleService.selectSysRoleById(sysUser.getRoleId());
        //5.把数据存储到session里面
        SecurityUtils.getSubject().getSession().setAttribute("sysRole", sysRole);
        //6.根据用户的情况来构建AuthenticationToken对象并返回
        //通常使用实现类SimpleAuthenticationInfo
        //以下信息是从数据库中获取的
        //1.PrincipalCollection ;认证的实体信息,可以使username,可以使用户表对应的实体类对象
        //2.credentials ;密码
        String password = sysUser.getPassword();
        //3.ByteSource ;当前realm对象的name,调用父类的getName()方法
        //4.加盐ByteSource credentialsSalt
        ByteSource bytes = ByteSource.Util.bytes(username);
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(sysUser, password, bytes, getName());
        return info;
    }

    public static void main(String[] args) {
        //salt    盐值
        SimpleHash md5 = new SimpleHash("MD5", "123456", "zzz", 1024);
        System.out.println(md5);
    }

    /**
     * 授权会被使用的方法
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //用来存放能访问的URL路径
//        HashSet<String> perms = new HashSet<>();
        //1.从principalCollection获取登录用户的信息
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
        //2.利用登陆的用户的信息来     查询当前的用户角色或权限(可能要查询数据库)
        //2.1先查询出这个用户对应的角色的ID
        Integer roleId = sysUser.getRoleId();
        //2.2由角色的ID去sys_role_menu表中查询所拥有的权限集合
        List<SysRoleMenu> sysRoleMenus = sysRoleMenuService.selectSysRoleMenuByIdList(roleId);
        //3.创建SimpleAuthorizationInfo,并设置其reles属性
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //4.遍历查询出来的权限集合 在sys_menu表里面查出能访问的相应的路径
        for (SysRoleMenu sysRoleMenu : sysRoleMenus) {
            //根据menuid去表中查询对应的数据
            Integer menuid = sysRoleMenu.getMenuid();
            SysMenu sysMenu = sysMenuService.selectSysMenuById(menuid);
            //把能访问的路径放到HashSet集合里面
//            perms.add(sysMenu.getUrl());
            info.addStringPermission(sysMenu.getUrl());
        }

        //5.返回SimpleAuthorizationInfo对象
        return info;
    }


//    @Override
//    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//        //用来存放能访问的URL路径
//        HashSet<String> perms = new HashSet<>();
//        //1.从principalCollection获取登录用户的信息
//        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
//        //2.利用登陆的用户的信息来     查询当前的用户角色或权限(可能要查询数据库)
//        //2.1先查询出这个用户对应的角色的ID
//        Integer roleId = sysUser.getRoleId();
//        //2.2由角色的ID去sys_role_menu表中查询所拥有的权限集合
//        List<SysRoleMenu> sysRoleMenus = sysRoleMenuService.selectSysRoleMenuByIdList(roleId);
//        //2.3遍历查询出来的权限集合 在sys_menu表里面查出能访问的相应的路径
//        for (SysRoleMenu sysRoleMenu : sysRoleMenus) {
//            //根据menuid去表中查询对应的数据
//            Integer menuid = sysRoleMenu.getMenuid();
//            SysMenu sysMenu = sysMenuService.selectSysMenuById(menuid);
//            //把能访问的路径放到HashSet集合里面
//            perms.add(sysMenu.getUrl());
//        }
//        //3.创建SimpleAuthorizationInfo,并设置其reles属性
//        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(perms);
//        //4.返回SimpleAuthorizationInfo对象
//        return info;
//    }
}
